#include <QDebug>

#include "cvimagecache.h"

CVImageCache *CVImageCache::staticObject = NULL;

class CVImageCache::Private
{
public:
    Private(){}
    ~Private(){}

    QHash<QString, QString> fileHash;
};

CVImageCache::CVImageCache() : d(new Private)
{
    session = CVSession::get();
    init();
}

void CVImageCache::init()
{
    QString cachePath = getCachePath();
    qDebug() << "Image Cache Path: " << cachePath;
    QDir dir(cachePath);
    if (!dir.exists())
    {
        bool result = dir.mkpath(cachePath);
        if (!result)
        {
            qDebug() << "Can not create path: " << cachePath;
            return;
        }
    }

    dir.setFilter(QDir::Files);
    QFileInfoList list = dir.entryInfoList();
    int fileSize = list.size();
    for (int i = 0; i < fileSize; ++i)
    {
        QFileInfo fileInfo = list.at(i);
        d->fileHash[fileInfo.completeBaseName()] = fileInfo.absoluteFilePath();
    }
}

CVImageCache::~CVImageCache()
{
    delete d;
}

CVImageCache *CVImageCache::instance()
{
    if(!staticObject)
    {
        staticObject = new CVImageCache();
    }
    return staticObject;
}

QImage CVImageCache::get(QUrl url)
{
    QString fileName = md5Path(url);
    if (contains(url))
    {
        QString filePath = d->fileHash[fileName];
        //qDebug() << "Cached image path: " << filePath;
        return QImage(filePath);
    }

    return QImage();
}

void CVImageCache::add(QUrl url, QImage image, CVImageCache::FILE_TYPE type)
{
    if (!contains(url))
    {
        QString fileName = md5Path(url);
        QString filePath = getCachePath() + fileName;
        switch (type)
        {
        case TYPE_PNG:
            filePath += ".png";
            break;
        case TYPE_JPG:
            filePath += ".jpg";
            break;
        case TYPE_GIF:
            filePath += ".gif";
            break;
        default:
            qDebug() << "Not image type set";
        }

        bool result = image.save(filePath);
        if (result)
        {
            QFile file(filePath);
            QFileInfo info(file);
            d->fileHash.insert(fileName, info.absoluteFilePath());
        }
    }
}


bool CVImageCache::contains(QUrl url)
{
    QString fileName = md5Path(url);
    return d->fileHash.contains(fileName);
}

void CVImageCache::clear(bool includeFiles)
{
    d->fileHash.clear();

    if (includeFiles)
    {
        QString cachePath = getCachePath();
        QDir dir(cachePath);
        dir.setFilter(QDir::Files);
        QFileInfoList list = dir.entryInfoList();
        int size = list.size();
        QFile *file;
        for (int i = 0; i < size; ++i)
        {
            QFileInfo fileInfo = list.at(i);
            file = new QFile(fileInfo.absoluteFilePath());
            file->remove();
        }
        delete file;
    }
}

QString CVImageCache::getCachePath()
{
    QString appPath = QApplication::applicationDirPath();
    CVNetwork *cvNetwork = session->getCurrentNetwork();
    QString network = "";
    if (cvNetwork != NULL)
    {
        network = cvNetwork->getUrl();
        //qDebug() << "[CVImageCache] Current network: " << network;
        if (!network.isEmpty())
        {
            network += "/";
        }
    }
    else
    {
        qDebug() << "[CVImageCache::getCachePath] Can not retrieve current network";
    }
    return appPath + "/" + network + "cache/";
}

QString CVImageCache::md5Path(QUrl url)
{
    QCryptographicHash md(QCryptographicHash::Md5);
    QByteArray ba, bb;
    ba.append(url.encodedHost() + url.encodedPath());
    md.addData(ba);
    bb = md.result();
    QTextCodec *codec = QTextCodec::codecForName("utf8");
    return codec->toUnicode(bb.toHex());
}
